package com.dhj.config;

import com.dhj.filter.JwtAuthenticationTokenFilter;
import com.dhj.handler.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;


/**
 * @author DaHuaJia
 * @Description Security配置类，配置接口过滤，异常处理等
 * @Date 2022-03-20 13:37:35
 */
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;

    @Autowired
    private AccessDeniedHandlerImpl accessDeniedHandler;

    @Autowired
    private AuthenticationEntryPointImpl authenticationEntryPoint;

    @Autowired
    private DhjSuccessHandler successHandler;

    @Autowired
    private DhjFailureHandler failureHandler;

    @Autowired
    private DhjLogoutSuccessHandler logoutSuccessHandler;

    /**
     * 创建BCryptPasswordEncoder注入容器
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }


    /**
     * 重写AuthenticationManager，不做任何修改，仅添加@Bean注解将给方法暴露出来，以便spring管理和调用
     */
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }


    /**
     * 接口校验过滤白名单
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {

        /*
        // 配置基于表单的认证成功处理器，也就是说，只有用户是通过表单提交登录信息才会调用该处理器。（cookie形式认证）
        // 目前我们使用的是调用登录接口，返回token的形式。也就不会用到该SuccessHandler。
        // 非前后端分离的项目才能使用这些处理器。
        http.formLogin()
                // 认证成功处理器
                .successHandler(successHandler)
                // 认证失败处理器
                .failureHandler(failureHandler);
        // 登出成功处理器
        http.logout().logoutSuccessHandler(logoutSuccessHandler);

        http.authorizeRequests().anyRequest().authenticated();
        */


        http
                //关闭csrf
                .csrf().disable()
                //不通过Session获取SecurityContext
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .authorizeRequests()
                // 对于登录接口 允许匿名访问
                .antMatchers("/user/login").anonymous()

                // 基于配置类的形式，给指定的请求路径添加指定权限
                .antMatchers("/configHello").hasAuthority("system:configHello")

                // 除上面外的所有请求全部需要鉴权认证
                .anyRequest().authenticated();

        // 将JwtAuthenticationTokenFilter过滤器添加到UsernamePasswordAuthenticationFilter之前
        http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);

        // 配置异常处理器
        http.exceptionHandling()
                // 配置认证失败处理器
                .authenticationEntryPoint(authenticationEntryPoint)
                // 配置授权失败处理器
                .accessDeniedHandler(accessDeniedHandler);

        // 允许跨域
        http.cors();

    }

    /**
     * 匿名访问：只有没携带token时才能访问
     * 允许访问：不管有没有携带token，都能访问
     */

}
